package com.pearlsoft.rms;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import com.pearlsoft.rms.VappConfig.VmConfig;
import com.pearlsoft.rms.vcenter.VcloudConnectionManager;
import com.vmware.vcloud.api.rest.schema.AvailableNetworksType;
import com.vmware.vcloud.api.rest.schema.CapacityWithUsageType;
import com.vmware.vcloud.api.rest.schema.CloneVAppParamsType;
import com.vmware.vcloud.api.rest.schema.ComposeVAppParamsType;
import com.vmware.vcloud.api.rest.schema.ComputeCapacityType;
import com.vmware.vcloud.api.rest.schema.InstantiationParamsType;
import com.vmware.vcloud.api.rest.schema.NetworkConfigSectionType;
import com.vmware.vcloud.api.rest.schema.NetworkConfigurationType;
import com.vmware.vcloud.api.rest.schema.NetworkConnectionSectionType;
import com.vmware.vcloud.api.rest.schema.NetworkConnectionType;
import com.vmware.vcloud.api.rest.schema.ObjectFactory;
import com.vmware.vcloud.api.rest.schema.ReferenceType;
import com.vmware.vcloud.api.rest.schema.SourcedCompositionItemParamType;
import com.vmware.vcloud.api.rest.schema.VAppNetworkConfigurationType;
import com.vmware.vcloud.api.rest.schema.VdcType;
import com.vmware.vcloud.api.rest.schema.ovf.CimString;
import com.vmware.vcloud.api.rest.schema.ovf.MsgType;
import com.vmware.vcloud.api.rest.schema.ovf.RASDType;
import com.vmware.vcloud.api.rest.schema.ovf.ResourceType;
import com.vmware.vcloud.api.rest.schema.ovf.SectionType;
import com.vmware.vcloud.sdk.OrgNetwork;
import com.vmware.vcloud.sdk.Organization;
import com.vmware.vcloud.sdk.Task;
import com.vmware.vcloud.sdk.VCloudException;
import com.vmware.vcloud.sdk.VM;
import com.vmware.vcloud.sdk.Vapp;
import com.vmware.vcloud.sdk.VappTemplate;
import com.vmware.vcloud.sdk.VcloudClient;
import com.vmware.vcloud.sdk.Vdc;
import com.vmware.vcloud.sdk.VirtualCpu;
import com.vmware.vcloud.sdk.VirtualDisk;
import com.vmware.vcloud.sdk.VirtualMemory;
import com.vmware.vcloud.sdk.admin.AdminOrganization;
import com.vmware.vcloud.sdk.admin.AdminVdc;
import com.vmware.vcloud.sdk.constants.FenceModeValuesType;
import com.vmware.vcloud.sdk.constants.IpAddressAllocationModeType;

/**
 * 
 * @author rainshow
 * @Created 2012-5-9 上午09:18:38
 */

@Service("cloudManager")
@Scope("singleton")
public class VcloudManagerImpl implements VcloudManager {
    private static Log logger = LogFactory.getLog(VcloudManagerImpl.class);
    private VcloudConnectionManager connectionManager;

    public Organization findOrgByName(String name) {
        Map<String, Organization> orgs = this.getOrgMap();
        Organization org = orgs.get(name);
        if (org == null) {
            logger.warn("组织[" + name + "]不存在");
            return null;
        }
        return org;
    }

    @Autowired
    public void setConnectionManager(VcloudConnectionManager connectionManager) {
        this.connectionManager = connectionManager;
    }

    public AdminOrganization findAdminOrgByName(String name) {
        try {
            VcloudClient client = connectionManager.getConnection().getClient();
            Map<String, ReferenceType> orgs = client.getVcloudAdmin().getAdminOrgRefsByName();
            ReferenceType orgRef = orgs.get(name);
            if (orgRef == null) {
                logger.warn("组织[" + name + "]不存在");
                return null;
            }
            return AdminOrganization.getAdminOrgByReference(client, orgRef);
        } catch (VCloudException e) {
            logger.error("组织[" + name + "]查找错误", e);
            return null;
        }
    }

    @Override
    public Map<String, Organization> getOrgMap() {
        Map<String, Organization> orgMap = new HashMap<String, Organization>();
        try {
            VcloudClient client = connectionManager.getConnection().getClient();
            Map<String, ReferenceType> orgs = client.getOrgRefsByName();
            for (Map.Entry<String, ReferenceType> entry : orgs.entrySet()) {
                Organization org = Organization.getOrganizationByReference(client, entry.getValue());
                orgMap.put(entry.getKey(), org);
            }
            return orgMap;
        } catch (VCloudException e) {
            logger.error("获取组织失败", e);
            return Collections.emptyMap();
        }
    }

    public Map<String, AdminOrganization> getAdminOrgMap() {
        Map<String, AdminOrganization> orgMap = new HashMap<String, AdminOrganization>();
        try {
            VcloudClient client = connectionManager.getConnection().getClient();
            Map<String, ReferenceType> adminOrgMap = client.getVcloudAdmin().getAdminOrgRefsByName();
            for (Map.Entry<String, ReferenceType> entry : adminOrgMap.entrySet()) {
                AdminOrganization org = AdminOrganization.getAdminOrgByReference(client, entry.getValue());
                orgMap.put(entry.getKey(), org);
            }
            return orgMap;
        } catch (VCloudException e) {
            logger.error("获取组织失败", e);
            return Collections.emptyMap();
        }
    }

    @Override
    public List<VM> getVMList(Vapp vapp) {
        try {
            return vapp.getChildrenVms();
        } catch (VCloudException e) {
            logger.error("获取VM失败", e);
            return Collections.emptyList();
        }
    }

    @Override
    public Map<String, Vapp> getVappMap(Vdc vdc) {
        Map<String, ReferenceType> vapps = vdc.getVappRefsByName();
        Map<String, Vapp> vappMap = new HashMap<String, Vapp>();
        try {
            VcloudClient client = connectionManager.getConnection().getClient();
            for (Map.Entry<String, ReferenceType> entry : vapps.entrySet()) {
                vappMap.put(entry.getKey(), Vapp.getVappByReference(client, entry.getValue()));
            }
            return vappMap;
        } catch (VCloudException e) {
            logger.error("获取Vapp失败", e);
            return Collections.emptyMap();
        }
    }

    @Override
    public Map<String, Vdc> getVdcMap(Organization org) {
        Map<String, ReferenceType> vdcs = org.getVdcRefsByName();
        Map<String, Vdc> vdcMap = new HashMap<String, Vdc>();
        try {
            VcloudClient client = connectionManager.getConnection().getClient();
            for (Map.Entry<String, ReferenceType> entry : vdcs.entrySet()) {
                vdcMap.put(entry.getKey(), Vdc.getVdcByReference(client, entry.getValue()));
            }
            return vdcMap;
        } catch (VCloudException e) {
            logger.error("获取VDC失败", e);
            return Collections.emptyMap();
        }
    }

    public Map<String, AdminVdc> getAdminVdcMap(AdminOrganization org) {
        Map<String, ReferenceType> vdcs = org.getAdminVdcRefsByName();
        Map<String, AdminVdc> vdcMap = new HashMap<String, AdminVdc>();
        try {
            VcloudClient client = connectionManager.getConnection().getClient();
            for (Map.Entry<String, ReferenceType> entry : vdcs.entrySet()) {
                vdcMap.put(entry.getKey(), AdminVdc.getAdminVdcByReference(client, entry.getValue()));
            }
            return vdcMap;
        } catch (VCloudException e) {
            logger.error("获取VDC失败", e);
            return Collections.emptyMap();
        }
    }

    public Map<String, OrgNetwork> getNetworkMap(Organization org) {
        Map<String, OrgNetwork> networkMap = new HashMap<String, OrgNetwork>();
        Map<String, ReferenceType> networks = org.getNetworkRefsByName();
        try {
            VcloudClient client = connectionManager.getConnection().getClient();
            for (Map.Entry<String, ReferenceType> entry : networks.entrySet()) {
                networkMap.put(entry.getKey(), OrgNetwork.getOrgNetworkByReference(client, entry.getValue()));
            }
            return networkMap;
        } catch (VCloudException e) {
            logger.error("获取Network失败", e);
            return Collections.emptyMap();
        }
    }

    public Vdc findVdc(String orgName, String vdcName) throws Exception {
        VcloudClient client = connectionManager.getConnection().getClient();
        Organization org = this.findOrgByName(orgName);
        ReferenceType vdcRef = org.getVdcRefByName(vdcName);
        return Vdc.getVdcByReference(client, vdcRef);
    }

    public Map<String, VM> findVmsMap(String orgName, String vdcName, String vappName, String[] vmNames)
            throws VCloudException {
        VcloudClient client = connectionManager.getConnection().getClient();
        Organization org = this.findOrgByName(orgName);
        ReferenceType vdcRef = org.getVdcRefByName(vdcName);
        Vdc vdc = Vdc.getVdcByReference(client, vdcRef);
        ReferenceType vappType = vdc.getVappRefByName(vappName);
        Vapp vapp = Vapp.getVappByReference(client, vappType);
        Map<String, VM> vms = new HashMap<String, VM>();
        for (VM vm : vapp.getChildrenVms()) {
            for (String vmName : vmNames) {
                if (vm.getResource().getName().equals(vmName)) {
                    vms.put(vm.getResource().getName(), vm);
                }
            }
        }
        return vms;
    }

    public VM findVm(String orgName, String vdcName, String vappName, String vmName) throws VCloudException {
        VcloudClient client = connectionManager.getConnection().getClient();
        Organization org = this.findOrgByName(orgName);
        ReferenceType vdcRef = org.getVdcRefByName(vdcName);
        Vdc vdc = Vdc.getVdcByReference(client, vdcRef);
        ReferenceType vappType = vdc.getVappRefByName(vappName);
        Vapp vapp = Vapp.getVappByReference(client, vappType);
        for (VM vm : vapp.getChildrenVms()) {
            if (vm.getResource().getName().equals(vmName)) {
                return vm;
            }
        }
        return null;
    }

    public List<VM> findVms(Vdc vdc) throws VCloudException {
        VcloudClient client = connectionManager.getConnection().getClient();
        Collection<ReferenceType> vapps = vdc.getVappRefs();
        List<VM> vms = new ArrayList<VM>();
        for (ReferenceType vappRef : vapps) {
            Vapp vapp = Vapp.getVappByReference(client, vappRef);
            vms.addAll(vapp.getChildrenVms());
        }
        return vms;
    }

    private void updateCpu(VM vm, int num) throws Exception {
        VirtualCpu cpu = vm.getCpu();
        cpu.setNoOfCpus(num);
        Task task = vm.updateCpu(cpu);
        task.waitForTask(0);
    }

    private void updateMem(VM vm, BigInteger size) throws Exception {
        VirtualMemory mem = vm.getMemory();
        mem.setMemorySize(size);
        Task task = vm.updateMemory(mem);
        task.waitForTask(0);
    }

    private void updateDisk(VM vm, int sizeInMB) throws Exception {
        List<VirtualDisk> disks = vm.getDisks();
        VirtualDisk sysDisk = null;
        for (VirtualDisk dsk : disks) {
            if (dsk.isHardDisk()) {
                sysDisk = dsk;
            }
        }
        CimString cimString = new CimString();
        Map<QName, String> cimAttributes = cimString.getOtherAttributes();
        cimAttributes.put(new QName("http://www.vmware.com/vcloud/v1.5", "busSubType", "vcloud"), sysDisk
                .getHardDiskBusType());
        cimAttributes.put(new QName("http://www.vmware.com/vcloud/v1.5", "busType", "vcloud"), "6");
        cimAttributes.put(new QName("http://www.vmware.com/vcloud/v1.5", "capacity", "vcloud"), sizeInMB + "");

        CimString setElementName = new CimString();
        setElementName.setValue("anything");
        CimString setInstanceID = new CimString();
        setInstanceID.setValue("anything");
        ResourceType setResourceType = new ResourceType();
        setResourceType.setValue("17");

        RASDType diskItemType = new RASDType();
        diskItemType.setElementName(setElementName);
        diskItemType.setInstanceID(setInstanceID);
        diskItemType.setResourceType(setResourceType);
        List<CimString> diskAttributes = diskItemType.getHostResource();
        diskAttributes.add(cimString);

        VirtualDisk disk = new VirtualDisk(diskItemType);

        disks.add(disk);
        Task task = vm.updateDisks(disks);
        task.waitForTask(0);
    }

    private void updateSection(VM vm) throws Exception {
        vm.getGuestCustomizationSection().setAdminPassword("abc123..");
        vm.getGuestCustomizationSection().setAdminPasswordAuto(false);
        Task task = vm.updateSection(vm.getGuestCustomizationSection());
        task.waitForTask(0);
    }

    public List<VM> createVapp(VappConfig config) {
        try {
            logger.info("创建项目[" + config.getName() + "]");
            String orgName = config.getOrgName();
            String vdcName = config.getVdcName();
            Vdc vdc = this.findVdc(orgName, vdcName);
            ComposeVAppParamsType vapp = this.createComposeParams(vdc, config);
            Vapp vap = vdc.composeVapp(vapp);
            List<Task> tasks = vap.getTasks();
            if (!tasks.isEmpty()) {
                tasks.get(0).waitForTask(0);
            }
            List<String> vmNames = new ArrayList<String>();
            for (VmConfig vc : config.getVmConfig()) {
                vmNames.add(vc.getName());
            }
            Map<String, VM> vmMap = this.findVmsMap(orgName, vdcName, config.getName(), vmNames
                    .toArray(new String[vmNames.size()]));
            for (VmConfig vc : config.getVmConfig()) {
                logger.info("开始更新虚拟机[" + vc.getName() + "]配置,CPU=" + vc.getCpuCount() + ",MEM=" + vc.getMemSize()
                        + "M,DISK=" + vc.getDiskSize() + "M");
                VM vm = vmMap.get(vc.getName());
                long start = System.currentTimeMillis();
                this.updateSection(vm);
                long end = System.currentTimeMillis();
                logger.info("用户信息更新完成，耗时:" + (end - start) / 1000 + "秒");
                this.updateCpu(vm, vc.getCpuCount());
                long end1 = System.currentTimeMillis();
                logger.info("CPU更新完成，耗时:" + (end1 - end) / 1000 + "秒");
                this.updateMem(vm, new BigInteger(vc.getMemSize() + ""));
                long end2 = System.currentTimeMillis();
                logger.info("内存更新完成，耗时:" + (end2 - end1) / 1000 + "秒");
                this.updateDisk(vm, vc.getDiskSize());
                long end3 = System.currentTimeMillis();
                logger.info("硬盘更新完成，耗时:" + (end3 - end2) / 1000 + "秒");
                vc.getIpAddress().clear();
                vc.getIpAddress().addAll(vm.getIpAddressesById().values());
            }
            return new ArrayList<VM>(vmMap.values());
        } catch (Throwable t) {
            logger.error(t);
            return Collections.emptyList();
        }
    }

    public boolean startVM(VM vm) throws VCloudException {
        Task task = vm.powerOn();
        try {
            task.waitForTask(0);
            return true;
        } catch (Throwable t) {
            return false;
        }
    }

    private ComposeVAppParamsType createComposeParams(Vdc vdc, VappConfig config) throws VCloudException {
        String newvAppNetwork = vdc.getAvailableNetworkRefs().iterator().next().getName();
        NetworkConfigurationType networkConfigurationType = new NetworkConfigurationType();
        if (vdc.getAvailableNetworkRefs().size() == 0) {
            System.out.println("No Networks in vdc to compose vapp");
            return null;
        }
        networkConfigurationType.setParentNetwork(vdc.getAvailableNetworkRefs().iterator().next());
        networkConfigurationType.setFenceMode(FenceModeValuesType.BRIDGED.value());

        VAppNetworkConfigurationType vAppNetworkConfigurationType = new VAppNetworkConfigurationType();
        vAppNetworkConfigurationType.setConfiguration(networkConfigurationType);
        vAppNetworkConfigurationType.setIsDeployed(true);
        vAppNetworkConfigurationType.setNetworkName(newvAppNetwork);

        NetworkConfigSectionType networkConfigSectionType = new NetworkConfigSectionType();
        MsgType networkInfo = new MsgType();
        networkConfigSectionType.setInfo(networkInfo);
        List<VAppNetworkConfigurationType> vAppNetworkConfigs = networkConfigSectionType.getNetworkConfig();
        vAppNetworkConfigs.add(vAppNetworkConfigurationType);

        InstantiationParamsType vappOrvAppTemplateInstantiationParamsType = new InstantiationParamsType();
        List<JAXBElement<? extends SectionType>> vappSections = vappOrvAppTemplateInstantiationParamsType.getSection();
        vappSections.add(new ObjectFactory().createNetworkConfigSection(networkConfigSectionType));

        ComposeVAppParamsType composeVAppParamsType = new ComposeVAppParamsType();
        //composeVAppParamsType.setDeploy(true);
        composeVAppParamsType.setInstantiationParams(vappOrvAppTemplateInstantiationParamsType);
        composeVAppParamsType.setName(config.getName());
        List<SourcedCompositionItemParamType> items = composeVAppParamsType.getSourcedItem();

        for (VmConfig vmConfig : config.getVmConfig()) {
            VappTemplate vm = this.findVmTemplate(vdc, vmConfig.getTemplate());
            String vmHref = vm.getReference().getHref();
            SourcedCompositionItemParamType vappTemplateItem = new SourcedCompositionItemParamType();
            ReferenceType vappTemplateVMRef = new ReferenceType();
            vappTemplateVMRef.setHref(vmHref);
            vappTemplateVMRef.setName(vmConfig.getName());
            vappTemplateItem.setSource(vappTemplateVMRef);
            NetworkConnectionSectionType networkConnectionSectionType = new NetworkConnectionSectionType();
            networkConnectionSectionType.setInfo(networkInfo);
            NetworkConnectionType networkConnectionType = new NetworkConnectionType();
            networkConnectionType.setNetwork(newvAppNetwork);
            networkConnectionType.setIsConnected(true);
            String ip = vmConfig.getIpAddress().isEmpty() ? null : vmConfig.getIpAddress().get(0);
            if (ip != null) {
                networkConnectionType.setIpAddressAllocationMode(IpAddressAllocationModeType.MANUAL.value());
                networkConnectionType.setIpAddress(ip);
            } else {
                networkConnectionType.setIpAddressAllocationMode(IpAddressAllocationModeType.POOL.value());
            }
            networkConnectionSectionType.getNetworkConnection().add(networkConnectionType);
            InstantiationParamsType vmInstantiationParamsType = new InstantiationParamsType();
            List<JAXBElement<? extends SectionType>> vmSections = vmInstantiationParamsType.getSection();
            vmSections.add(new ObjectFactory().createNetworkConnectionSection(networkConnectionSectionType));
            vappTemplateItem.setInstantiationParams(vmInstantiationParamsType);
            items.add(vappTemplateItem);
        }
        return composeVAppParamsType;
    }

    private VappTemplate findVmTemplate(Vdc vdc, String template) throws VCloudException {
        VcloudClient client = connectionManager.getConnection().getClient();
        Collection<ReferenceType> templates = vdc.getVappTemplateRefs();
        for (ReferenceType t : templates) {
            if (t.getName().equals(template)) {
                VappTemplate vt = VappTemplate.getVappTemplateByReference(client, t);
                return vt.getChildren().get(0);
            }
        }
        return null;
    }

    public VappTemplate findVappTemplate(String orgName, VmConfig vmc) throws VCloudException {
        VcloudClient client = connectionManager.getConnection().getClient();
        Organization org = this.findOrgByName(orgName);
        Map<String, ReferenceType> orgVdc = org.getVdcRefsByName();
        for (Map.Entry<String, ReferenceType> entry : orgVdc.entrySet()) {
            Vdc vdc = Vdc.getVdcByReference(client, entry.getValue());
            for (ReferenceType vappTemplateRef : vdc.getVappTemplateRefs()) {
                if (vappTemplateRef.getName().equals(vmc.getTemplate())) {
                    return VappTemplate.getVappTemplateByReference(client, vappTemplateRef);
                }
            }
        }
        return null;
    }

    @Override
    public Map<String, String> getVdcResource(String orgName, String vdcName) throws Exception {
        Vdc vdc = this.findVdc(orgName, vdcName);
        return getVdcResource(vdc);
    }

    public Map<String, String> getVdcResource(Vdc vdc) throws Exception {
        this.connectionManager.getConnection().getClient().getQueryService();
        List<VM> vms = this.findVms(vdc);
        int cpuCount = 0;
        for (VM vm : vms) {
            cpuCount += vm.getCpu().getNoOfCpus();
        }
        Map<String, String> resources = new HashMap<String, String>();
        resources.put("cpu.count", cpuCount + "");
        resources.put("cpu", vdc.getResource().getComputeCapacity().getCpu().getAllocated() + "");
        resources.put("mem", vdc.getResource().getComputeCapacity().getMemory().getAllocated() + "");
        resources.put("disk", vdc.getResource().getStorageCapacity().getAllocated() + "");
        return resources;
    }

    @Override
    public void setLogLevel(Level level) {
        VcloudClient.setLogLevel(level);
    }

    public Map<String, String> getVdcAvailableResource(String orgName, String vdcName) throws Exception {
        return getVdcAvailableResource(this.findVdc(orgName, vdcName));
    }

    public Map<String, String> getVdcAvailableResource(Vdc vdc) throws Exception {
        Map<String, String> result = new HashMap<String, String>();
        try {
            float cpuThreshold = Float.parseFloat(System.getProperty("CPU_THRESHOLD", "0.8"));
            float memThreshold = Float.parseFloat(System.getProperty("MEM_THRESHOLD", "1.2"));
            float diskThreshold = Float.parseFloat(System.getProperty("DISK_THRESHOLD", "0.9"));
            AvailableNetworksType availableNetworks = vdc.getResource().getAvailableNetworks();
            boolean networkAvailable = availableNetworks.getNetwork().size() > 0;
            result.put("network", networkAvailable ? "1" : "0");
            result.put("network_available", availableNetworks.getNetwork().size() + "");
            CapacityWithUsageType cpu = vdc.getResource().getComputeCapacity().getCpu();
            boolean cpuAvailable = cpu.getUsed() / cpu.getAllocated() < cpuThreshold;
            result.put("cpu", cpuAvailable ? "1" : "0");
            result.put("cpu_available", cpu.getAllocated() - cpu.getUsed() + " MHz");
            CapacityWithUsageType mem = vdc.getResource().getComputeCapacity().getMemory();
            result.put("mem", mem.getUsed() / mem.getAllocated() > memThreshold ? "0" : "1");
            result.put("mem_available", mem.getAllocated() - mem.getUsed() + " M");
            CapacityWithUsageType disk = vdc.getResource().getStorageCapacity();
            result.put("disk", disk.getUsed() / disk.getAllocated() > diskThreshold ? "0" : "1");
            result.put("disk_available", disk.getAllocated() - disk.getUsed() + " M");
            return result;
        } catch (Exception e) {
            logger.error(e);
            result.put("cpu", "0");
            result.put("cpu_available", "0");
            result.put("mem", "0");
            result.put("memavailable", "0");
            result.put("network", "0");
            result.put("network_available", "0");
            result.put("disk", "0");
            result.put("disk_available", "0");
            return result;
        }
    }

    public String acquireTicket(String orgName, String vdcName, String vappName, String vmName) throws Exception {
        VM vm = this.findVm(orgName, vdcName, vappName, vmName);
        if (vm != null) {
            return vm.acquireTicket().getValue();
        }
        throw new Exception("VM[" + vmName + "] is not found");
    }

    @Override
    public String getVmPassword(String orgName, String vdcName, String vappName, String vmName) throws Exception {
        VM vm = this.findVm(orgName, vdcName, vappName, vmName);
        return vm.getGuestCustomizationSection().getAdminPassword();
    }

    @Override
    public void updateVm(String orgName, String vdcName, String vappName, String vmName, int cpuNum, int memSize,
            int networkIncrement, int diskIncrement) throws Exception {
        VM vm = findVm(orgName, vdcName, vappName, vmName);
        logger.info("开始更新虚拟机[" + vmName + "]配置,CPU=" + cpuNum + ",MEM=" + memSize + "M,DISK=" + diskIncrement + "M");
        long end = System.currentTimeMillis();
        this.updateCpu(vm, cpuNum);
        long end1 = System.currentTimeMillis();
        logger.info("CPU更新完成，耗时:" + (end1 - end) / 1000 + "秒");
        this.updateMem(vm, new BigInteger(memSize + ""));
        long end2 = System.currentTimeMillis();
        logger.info("内存更新完成，耗时:" + (end2 - end1) / 1000 + "秒");
        this.updateDisk(vm, diskIncrement);
        long end3 = System.currentTimeMillis();
        logger.info("硬盘更新完成，耗时:" + (end3 - end2) / 1000 + "秒");
    }

    public void cloneVapp(String orgName, String vdcName, String vappName, String targetOrgName, String targetVdcName,
            String baseline) throws Exception {
        Vdc vdc = this.findVdc(orgName, vdcName);
        Vdc targetVdc = this.findVdc(targetOrgName, targetVdcName);
        Map<String, Vapp> vapps = this.getVappMap(vdc);
        Vapp vapp = vapps.get(vappName);
        CloneVAppParamsType paramsType = new CloneVAppParamsType();
        paramsType.setName(vappName + "-" + baseline);
        paramsType.setDescription("项目[" + vappName + "]备份，对应项目基线[" + baseline + "]");
        paramsType.setSource(vapp.getReference());
        targetVdc.cloneVapp(paramsType);
    }

    @Override
    public void closeVapp(Vapp vapp) throws Exception {
        Task task = vapp.powerOff();
        task.waitForTask(0);
    }

    @Override
    public Vapp findVapp(String orgName, String vdcName, String vappName) throws Exception {
        return this.findVapp(this.findVdc(orgName, vdcName), vappName);
    }

    public Vapp findVapp(Vdc vdc, String vappName) throws Exception {
        Map<String, Vapp> vapp = this.getVappMap(vdc);
        return vapp.get(vappName);
    }

    @Override
    public void startVapp(Vapp vapp) throws Exception {
        Task task = vapp.powerOn();
        task.waitForTask(0);
    }

    public static void main(String[] args) throws Throwable {
        VcloudManagerImpl vm = new VcloudManagerImpl();
        vm.setLogLevel(Level.OFF);

        Map<String, Organization> orgs = vm.getOrgMap();
        for (Map.Entry<String, Organization> entry : orgs.entrySet()) {
            System.out.println("name:" + entry.getKey() + ",org:" + entry.getValue().getReference().getHref());
        }
        Organization org = vm.findOrgByName("test");

        Map<String, Vdc> vdcs = vm.getVdcMap(org);
        for (Map.Entry<String, Vdc> entry : vdcs.entrySet()) {
            Vdc v = entry.getValue();
            VdcType vtype = v.getResource();
            CapacityWithUsageType ctype = vtype.getStorageCapacity();
            ComputeCapacityType cctype = vtype.getComputeCapacity();
            CapacityWithUsageType cpu = cctype.getCpu();
            CapacityWithUsageType mem = cctype.getMemory();
            System.out.println("vdc name:" + entry.getKey() + ",disk=>limit:" + ctype.getLimit() + ",units:"
                    + ctype.getUnits() + ",allocated:" + ctype.getAllocated() + ",used:" + ctype.getUsed()
                    + ",overhead:" + ctype.getOverhead());
            System.out.println("vdc name:" + entry.getKey() + ",cpu=>limit:" + cpu.getLimit() + ",units:"
                    + cpu.getUnits() + ",allocated:" + cpu.getAllocated() + ",used:" + cpu.getUsed() + ",overhead:"
                    + cpu.getOverhead());
            System.out.println("vdc name:" + entry.getKey() + ",mem=>limit:" + mem.getLimit() + ",units:"
                    + mem.getUnits() + ",allocated:" + mem.getAllocated() + ",used:" + mem.getUsed() + ",overhead:"
                    + mem.getOverhead());
        }

        Map<String, OrgNetwork> networks = vm.getNetworkMap(org);
        for (Map.Entry<String, OrgNetwork> entry : networks.entrySet()) {
            OrgNetwork network = entry.getValue();
            System.out.println("network name:" + entry.getKey() + "," + network.getResource().getConfiguration());
        }

        //VappTemplate tpl = vm.findVappTemplate("test", "test", "XP_TPL");
        //System.out.println(tpl.getResource().getName());
        VappConfig config = new VappConfig("vapp100");
        config.setOrgName("test");
        config.setVdcName("test");
        config.addVm("vapp100-host-1", "XP_TPL", 2, 1, 1024, 3 * 1024, 8);
        config.addVm("vapp100-host-2", "LINUX_TPL", 2, 1, 1024, 3 * 1024, 8);
        List<VM> vms = vm.createVapp(config);
        System.out.println(vms.size());
    }

}
